#include "Chatbox.hpp"
#include "GenericKeys.h"
#include "GLPrimitives.h"
#include "Lua.h"

Chatbox::Chatbox()
{
	m_location.x = 0;
	m_location.y = 0;

	m_dimensions.w = 0;
	m_dimensions.h = 0;

	m_backgroundColor.r = 0;
	m_backgroundColor.g = 0;
	m_backgroundColor.b = 0;
	
	m_fontColor.r = 0;
	m_fontColor.g = 0;
	m_fontColor.b = 0;

	m_maxInputSize = 128;
	m_maxLogSize = 25;
	m_log.reserve(m_maxLogSize);
	m_font = "onuava";

	m_active = false;
	m_deleteTicks = 400;
	m_textFadeTime = 3000; // 20 seconds
	m_textFadeSpeed = .015f;
	m_scrollCurrentPos = m_log.size() - 1;
}

void Chatbox::HandleDeleteEvents(bool deleteItems) // How many Delete events
{
	// if backspace is pressed and we are active
	if(m_active && deleteItems)
	{
		if(m_BackspaceFilter.IsRunning() == false)
			m_BackspaceFilter.Restart();

		if(m_BackspaceFilter.GetElapsedMilliseconds() > m_deleteTicks)
			m_inputDevice.PopBack();

	}
	else
	{
		m_BackspaceFilter.Restart();
		m_BackspaceFilter.Stop();
	}
}

void Chatbox::HandleEvents(const SDL_Event& event, Uint8 *keystates)
{
	
    if( event.type == SDL_KEYDOWN )
    {   

		if((event.key.keysym.sym == SDLK_PAGEDOWN))
		{
			m_scrollCurrentPos++;

			if(m_scrollCurrentPos >= m_log.size())
				m_scrollCurrentPos = m_log.size() - 1;

			m_log[m_scrollCurrentPos].tmr.Restart();
			m_log[m_scrollCurrentPos].currentFadeLevel = 1.0;
		}

		if((event.key.keysym.sym == SDLK_PAGEUP))
		{
			m_scrollCurrentPos--;
			if(m_scrollCurrentPos < 0)
				m_scrollCurrentPos = 0;
			m_log[m_scrollCurrentPos].tmr.Restart();
			m_log[m_scrollCurrentPos].currentFadeLevel = 1.0;
		}
	

		if((event.key.keysym.sym == SDLK_RETURN) && (m_active == false))
		{
			m_active = true;
			m_blinker.Restart();
		}

			

			// if enter was pressed
			if(m_inputDevice.HandleEvents(event))
			{		
					// while our message is too long
					LogMessage message;
					message.str = m_inputDevice.GetString();
					string deletedCharacters;
					while(Key->GetFont(m_font)->calcStringWidth(message.str) > m_dimensions.w)
					{
						
						do {
							deletedCharacters.push_back(message.str[message.str.length() - 1]);
							message.str.erase(message.str.length() - 1);
						} while((message.str.length() > 0) && (message.str[message.str.length() - 1] != ' '));

						if(message.str.length() == 0) // if a single word was longer than the chat box
						{
							// restore our message
							message.str.clear();
							for(int p = deletedCharacters.size() - 1; p >= 0; --p)
								message.str.push_back(deletedCharacters[p]);
							deletedCharacters.clear();
							// trim until its small enough
							do {
								deletedCharacters.push_back(message.str[message.str.length() - 1]);
								message.str.erase(message.str.length() - 1);
							} while((message.str.length() > 0) && (Key->GetFont(m_font)->calcStringWidth(message.str) >= m_dimensions.w));
						}

						if(Key->GetFont(m_font)->calcStringWidth(message.str) <= m_dimensions.w) // if message is short enough
						{
							message.tmr.Restart();
							m_log.push_back(message);

							// deleted characters is stored backwords
							message.str.clear();
							for(int p = deletedCharacters.size() - 1; p >= 0; --p)
								message.str.push_back(deletedCharacters[p]);
							deletedCharacters.clear();
						
						}	
					}
					
					// add the final bits of the message that will not exceed the chat panel's boundraies
					message.tmr.Restart();
					m_log.push_back(message);
					message.str = "LOG_COMMAND:: AddAdditionalSpacing";
					message.tmr.Restart();
					m_log.push_back(message);
					m_scrollCurrentPos = m_log.size() - 1;
	
				m_active = false;
				m_blinker.Stop();
			}

			
			
		

	}

}

void Chatbox::AddMessage(char* message)
{
	LogMessage temp;
	temp.str.append(message);
	temp.tmr.Restart();
	temp.currentFadeLevel = 1.0;
	m_log.push_back(temp);
}
void Chatbox::Render()
{
	// This define basically determines how to display the chat box:  as a box or as text that appears on the left side of the screen.
	#define RENDER_AND_BOUND_BY_BOX

	bool render_only_if_text_is_active = false;
	for(int i = 0; i < m_log.size(); ++i)
		if(m_log[i].currentFadeLevel > 0.01)
			render_only_if_text_is_active = true;

	// draw our background
	#ifdef RENDER_AND_BOUND_BY_BOX
	if(render_only_if_text_is_active)
		DrawPrimitives->DrawRectangle(m_location.x, m_location.y, m_location.x + m_dimensions.w, m_location.y + m_dimensions.h, m_backgroundColor);
	#endif

	// draw our previous messeges
	int fontSpacing = 4;
	int rectSpacing = 2;
	Coords loc = m_location;
	loc.x += fontSpacing;
	loc.y += m_dimensions.h - Key->GetFont(m_font)->getHeight();

	// draw the border around the chat box
	#ifdef RENDER_AND_BOUND_BY_BOX
	if(render_only_if_text_is_active)
	{
		int x1 = m_location.x, x2 = m_location.x + m_dimensions.w, y1 = m_location.y, y2 = m_location.y + m_dimensions.h;
		DrawPrimitives->DrawRectangle(x1, y1, x1+rectSpacing, y2,	black);
		DrawPrimitives->DrawRectangle(x1, y1, x2, y1+rectSpacing,	black);
		DrawPrimitives->DrawRectangle(x2, y1, x2-rectSpacing, y2,	black);
		DrawPrimitives->DrawRectangle(x1, y2, x2, y2-rectSpacing,	black);
	}
	#endif

	if(render_only_if_text_is_active)
	{
		//for(int i = m_log.size() - 1; i >= 0; --i)
		for(int i = m_scrollCurrentPos; i >= 0; --i)
		{
			#ifdef RENDER_AND_BOUND_BY_BOX
			if(loc.y <= (m_location.y + rectSpacing))
			{
				m_log[i].currentFadeLevel = -10.0;
				continue;
			}
			#endif

			if(m_log[i].str == "LOG_COMMAND:: AddAdditionalSpacing")
			{
				m_log[i].currentFadeLevel = -10.0;
				loc.y -= (Key->GetFont(m_font)->getHeight() / 4);
				continue;
			}

			if((m_log[i].tmr.GetElapsedMilliseconds() > m_textFadeTime)) // if we are fading out
			{
				if(m_log[i].currentFadeLevel > 0.0)
				{
					m_log[i].currentFadeLevel -= m_textFadeSpeed;
					OGL_Color fadeFontColor = m_fontColor;
					fadeFontColor.a = m_log[i].currentFadeLevel;
					Key->GetFont(m_font)->drawText(loc.x, loc.y, m_log[i].str, fadeFontColor);
					#ifndef RENDER_AND_BOUND_BY_BOX
					DrawPrimitives->DrawRectangle(loc.x - rectSpacing, loc.y, loc.x + Key->GetFont(m_font).calcStringWidth(m_log[i].str) + rectSpacing, loc.y + Key->GetFont(m_font).getHeight(), m_backgroundColor, fadeFontColor.a);
					#endif
				}
			}
			else
			{
				Key->GetFont(m_font)->drawText(loc.x, loc.y, m_log[i].str, m_fontColor);
				m_log[i].currentFadeLevel = 1.0;
				#ifndef RENDER_AND_BOUND_BY_BOX
				DrawPrimitives->DrawRectangle(loc.x - rectSpacing, loc.y, loc.x + Key->GetFont(m_font).calcStringWidth(m_log[i].str) + rectSpacing, loc.y + Key->GetFont(m_font).getHeight(), m_backgroundColor);
				#endif
			}

			

			loc.y -= Key->GetFont(m_font)->getHeight()/* + spacing*/;
		}
	}

	// draw our current message	(if this gets too slow, use the commented out line below
	if(m_active)
	{
		string drawnInput = m_inputDevice.GetString();
		while(Key->GetFont(m_font)->calcStringWidth(drawnInput) >= (m_dimensions.w - (rectSpacing)))
		{
			drawnInput.erase(drawnInput.begin());
			//drawnInput.erase(drawnInput.begin(), drawnInput.begin() + 3);
		}
		Key->GetFont(m_font)->drawText(m_location.x + rectSpacing, m_location.y + m_dimensions.h + fontSpacing, drawnInput, m_fontColor);

	
		DrawPrimitives->DrawRectangle(m_location.x, m_location.y + m_dimensions.h, m_location.x + m_dimensions.w, m_location.y + m_dimensions.h + rectSpacing + fontSpacing + Key->GetFont(m_font)->getHeight(), m_backgroundColor);
	
				

		int BLINKER_TIME = 500;
		if((m_blinker.GetElapsedMilliseconds() > BLINKER_TIME))
		{
			int x_ = Key->GetFont(m_font)->calcStringWidth(drawnInput) + m_location.x;
			int y_ =  m_location.y + m_dimensions.h;
			DrawPrimitives->DrawRectangle(x_ + rectSpacing, y_, x_ + (rectSpacing * 3), y_ + Key->GetFont(m_font)->getHeight(), black);
			m_blinker.Restart();
		}
	}
}